home *** CD-ROM | disk | FTP | other *** search
/ Atari Mega Archive 1 / Atari Mega Archive - Volume 1.iso / telecomm / sticpsrc.lzh / SOURCE.ARC / FTPCLI.C < prev    next >
C/C++ Source or Header  |  1990-08-10  |  19KB  |  784 lines

  1. /* FTP client (interactive user) code */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "mbuf.h"
  5. #include "netuser.h"
  6. #include "icmp.h"
  7. #include "timer.h"
  8. #include "tcp.h"
  9. #include "ftp.h"
  10. #include "session.h"
  11. #include "cmdparse.h"
  12. #ifdef ATARI_ST
  13. # ifdef __TURBOC__
  14. #  include <tos.h>
  15. # else
  16. #  include <osbind.h>
  17. # endif
  18. #endif
  19.  
  20. extern struct session *current;
  21. extern char nospace[];
  22. extern char badhost[];
  23. static char notsess[] = "Not an FTP session!\n";
  24. static char cantwrite[] = "Can't write %s\n";
  25. static char cantread[] = "Can't read %s\n";
  26.  
  27. #if (defined(MSC) || (defined(ATARI_ST) && defined(__TURBOC__)))
  28. static int sndftpmsg(struct ftp *ftp,char *fmt,...);
  29. #endif
  30.  
  31. int donothing(),doftpcd(),dolist(),doget(),dols(),doput(),dotype(),doabort(),
  32.     domkdir(),dormdir(),dotput();
  33.  
  34. struct cmds ftpabort[] = {
  35.     "",        donothing,    0,    NULLCHAR,        NULLCHAR,
  36.     "abort",    doabort,    0,    NULLCHAR,        NULLCHAR,
  37.     NULLCHAR,    NULLFP,        0,    "Only valid command is \"abort\"", NULLCHAR
  38. };
  39.  
  40. struct cmds ftpcmds[] = {
  41.     "",        donothing,    0,    NULLCHAR,        NULLCHAR,
  42.     "cd",        doftpcd,    2,    "<directory>",        NULLCHAR,
  43.     "dir",        dolist,        0,    NULLCHAR,        NULLCHAR,
  44.     "list",        dolist,        0,    NULLCHAR,        NULLCHAR,
  45.     "get",        doget,        2,    "<remotefile> [<localfile>]",    NULLCHAR,
  46.     "ls",        dols,        0,    NULLCHAR,        NULLCHAR,
  47.     "mkdir",    domkdir,    2,    "<directory>",        NULLCHAR,
  48.     "nlst",        dols,        0,    NULLCHAR,        NULLCHAR,
  49.     "rmdir",    dormdir,    2,    "<directory>",        NULLCHAR,
  50.     "put",        doput,        2,    "<localfile> [<remotefile>]",    NULLCHAR,
  51.     "type",        dotype,        0,    NULLCHAR,        NULLCHAR,
  52. #if (defined(MSDOS))
  53.     "tput",        dotput,        2,    "<localspec>",        NULLCHAR,
  54. #endif
  55. #if (defined(ATARI_ST))
  56.     "tput",        dotput,        2,    "<localspec> [x]",    NULLCHAR,
  57. #endif
  58.     NULLCHAR,    NULLFP,        0,    NULLCHAR,        NULLCHAR
  59. };
  60.  
  61. /* Handle top-level FTP command */
  62. doftp(argc,argv)
  63. int argc;
  64. char *argv[];
  65. {
  66.     int32 resolve();
  67.     int ftpparse();
  68.     void ftpccr(),ftpccs();
  69.     struct session *s;
  70.     struct ftp *ftp,*ftp_create();
  71.     struct tcb *tcb;
  72.     struct socket lsocket,fsocket;
  73.     char tos = 0;
  74.  
  75.     lsocket.address = ip_addr;
  76.     lsocket.port = lport++;
  77.     if((fsocket.address = resolve(argv[1])) == 0){
  78.         printf(badhost,argv[1]);
  79.         return 1;
  80.     }
  81.     if(argc < 3)
  82.         fsocket.port = FTP_PORT;
  83.     else {
  84.         if((fsocket.port = atoi(argv[2])) == 0)
  85.             fsocket.port = FTP_PORT;
  86.         tos = get_tos(argv[3]);
  87.     }
  88.     /* Allocate a session control block */
  89.     if((s = newsession()) == NULLSESSION){
  90.         printf("Too many sessions\n");
  91.         return 1;
  92.     }
  93.     current = s;
  94.     if((s->name = malloc((unsigned)strlen(argv[1])+1)) != NULLCHAR)
  95.         strcpy(s->name,argv[1]);
  96.     s->type = FTP;
  97.     s->parse = ftpparse;
  98.  
  99.     /* Allocate an FTP control block */
  100.     if((ftp = ftp_create(0)) == NULLFTP){
  101.         s->type = FREE;
  102.         printf(nospace);
  103.         return 1;
  104.     }
  105.     ftp->state = COMMAND_STATE;
  106.     s->cb.ftp = ftp;    /* Downward link */
  107.     ftp->session = s;    /* Upward link */
  108.  
  109.     /* Now open the control connection */
  110.     tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,
  111.         0,ftpccr,NULLVFP,ftpccs,tos,(char *)ftp);
  112.     ftp->control = tcb;
  113.     go();
  114.     return 0;
  115. }
  116. /* Parse user FTP commands */
  117. int
  118. ftpparse(line,len)
  119. char *line;
  120. int16 len;
  121. {
  122.     struct mbuf *bp;
  123.  
  124.     if(current->cb.ftp->state != COMMAND_STATE){
  125.         /* The only command allowed in data transfer state is ABORT */
  126.         if(cmdparse(ftpabort,line) == -1){
  127.             printf("Transfer in progress; only ABORT is acceptable\n");
  128.         }
  129.         fflush(stdout);
  130.         return;
  131.     }
  132.  
  133.     /* Save it now because cmdparse modifies the original */
  134.     bp = qdata(line,len);
  135.  
  136.     if(cmdparse(ftpcmds,line) == -1){
  137.         /* Send it direct */
  138.         if(bp != NULLBUF)
  139.             send_tcp(current->cb.ftp->control,bp);
  140.         else
  141.             printf(nospace);
  142.     } else {
  143.         free_p(bp);
  144.     }
  145.     fflush(stdout);
  146. }
  147. /* Handle null line to avoid trapping on first command in table */
  148. static
  149. int
  150. donothing(argc,argv)
  151. int argc;
  152. char *argv[];
  153. {
  154.     return 0;
  155. }
  156. /* Translate 'cd' to 'cwd' for convenience */
  157. static
  158. int
  159. doftpcd(argc,argv)
  160. int argc;
  161. char *argv[];
  162. {
  163.     register struct ftp *ftp;
  164.  
  165.     ftp = current->cb.ftp;
  166.     return sndftpmsg(ftp,"CWD %s\r\n",argv[1]);
  167. }
  168. /* Translate 'mkdir' to 'xmkd' for convenience */
  169. static
  170. int
  171. domkdir(argc,argv)
  172. int argc;
  173. char *argv[];
  174. {
  175.     register struct ftp *ftp;
  176.  
  177.     ftp = current->cb.ftp;
  178.     return sndftpmsg(ftp,"XMKD %s\r\n",argv[1]);
  179. }
  180. /* Translate 'rmdir' to 'xrmd' for convenience */
  181. static
  182. int
  183. dormdir(argc,argv)
  184. int argc;
  185. char *argv[];
  186. {
  187.     register struct ftp *ftp;
  188.  
  189.     ftp = current->cb.ftp;
  190.     return sndftpmsg(ftp,"XRMD %s\r\n",argv[1]);
  191. }
  192. /* Handle "type" command from user */
  193. static
  194. int
  195. dotype(argc,argv)
  196. int argc;
  197. char *argv[];
  198. {
  199.     register struct ftp *ftp;
  200.  
  201.     ftp = current->cb.ftp;
  202.     if(argc < 2){
  203.         switch(ftp->type){
  204.         case IMAGE_TYPE:
  205.             printf("Image\n");
  206.             break;
  207.         case ASCII_TYPE:
  208.             printf("Ascii\n");
  209.             break;
  210.         }
  211.         return 0;
  212.     }
  213.     switch(*argv[1]){
  214.     case 'i':
  215.     case 'b':
  216.         ftp->type = IMAGE_TYPE;
  217.         sndftpmsg(ftp,"TYPE I\r\n");
  218.         break;
  219.     case 'a':
  220.         ftp->type = ASCII_TYPE;
  221.         sndftpmsg(ftp,"TYPE A\r\n");
  222.         break;
  223.     case 'l':
  224.         if (argc > 2){
  225.             ftp->type = IMAGE_TYPE;
  226.             sndftpmsg(ftp,"TYPE L %s\r\n",argv[2]);
  227.             break;
  228.         }
  229.         /* no arg after TYPE L, drop in default
  230.            instead of generating BUS ERROR on Atari ST (and others) */
  231.     default:
  232.         printf("Invalid type %s\n",argv[1]);
  233.         return 1;
  234.     }
  235.     return 0;
  236. }
  237. /* Start receive transfer. Syntax: get <remote name> [<local name>] */
  238. static
  239. doget(argc,argv)
  240. int argc;
  241. char *argv[];
  242. {
  243.     void ftpdr(),ftpcds();
  244.     char *remotename,*localname;
  245.     register struct ftp *ftp;
  246.     char *mode;
  247.  
  248.     if((ftp = current->cb.ftp) == NULLFTP){
  249.         printf(notsess);
  250.         return 1;
  251.     }
  252.     remotename = argv[1];
  253.     if(argc < 3)
  254.         localname = remotename;
  255.     else
  256.         localname = argv[2];
  257.  
  258.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  259.         fclose(ftp->fp);
  260.  
  261.     if(ftp->type == IMAGE_TYPE)
  262.         mode = binmode[WRITE_BINARY];
  263.     else
  264.         mode = "w";
  265.  
  266.     if((ftp->fp = fopen(localname,mode)) == NULLFILE){
  267.         printf(cantwrite,localname);
  268.         return 1;
  269.     }
  270.     ftp->state = RECEIVING_STATE;
  271.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  272.  
  273.     /* Generate the command to start the transfer */
  274.     return sndftpmsg(ftp,"RETR %s\r\n",remotename);
  275. }
  276. /* List remote directory. Syntax: dir <remote directory/file> [<local name>] */
  277. static
  278. dolist(argc,argv)
  279. int argc;
  280. char *argv[];
  281. {
  282.     void ftpdr(),ftpcds();
  283.     register struct ftp *ftp;
  284.  
  285.     if((ftp = current->cb.ftp) == NULLFTP){
  286.         printf(notsess);
  287.         return 1;
  288.     }
  289.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  290.         fclose(ftp->fp);
  291.  
  292.     if(argc < 3){
  293.         ftp->fp = stdout;
  294.     } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
  295.         printf(cantwrite,argv[2]);
  296.         return 1;
  297.     }
  298.     ftp->state = RECEIVING_STATE;
  299.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  300.     /* Generate the command to start the transfer
  301.      * It's done this way to avoid confusing the 4.2 FTP server
  302.      * if there's no argument
  303.      */
  304.     if(argc > 1)
  305.         return sndftpmsg(ftp,"LIST %s\r\n",argv[1]);
  306.     else
  307.         return sndftpmsg(ftp,"LIST\r\n");
  308. }
  309. /* Abbreviated (name only) list of remote directory.
  310.  * Syntax: ls <remote directory/file> [<local name>]
  311.  */
  312. static
  313. dols(argc,argv)
  314. int argc;
  315. char *argv[];
  316. {
  317.     void ftpdr(),ftpcds();
  318.     register struct ftp *ftp;
  319.  
  320.     if((ftp = current->cb.ftp) == NULLFTP){
  321.         printf(notsess);
  322.         return 1;
  323.     }
  324.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  325.         fclose(ftp->fp);
  326.  
  327.     if(argc < 3){
  328.         ftp->fp = stdout;
  329.     } else if((ftp->fp = fopen(argv[2],"w")) == NULLFILE){
  330.         printf(cantwrite,argv[2]);
  331.         return 1;
  332.     }
  333.     ftp->state = RECEIVING_STATE;
  334.     ftpsetup(ftp,ftpdr,NULLVFP,ftpcds);
  335.     /* Generate the command to start the transfer */
  336.     if(argc > 1)
  337.         return sndftpmsg(ftp,"NLST %s\r\n",argv[1]);
  338.     else
  339.         return sndftpmsg(ftp,"NLST\r\n");
  340. }
  341. /* Start transmit. Syntax: put <local name> [<remote name>] */
  342. static
  343. doput(argc,argv)
  344. int argc;
  345. char *argv[];
  346. {
  347.     void ftpdt(),ftpcds();
  348.     char *remotename,*localname;
  349.     char *mode;
  350.     struct ftp *ftp;
  351.  
  352.     if((ftp = current->cb.ftp) == NULLFTP){
  353.         printf(notsess);
  354.         return 1;
  355.     }
  356.     localname = argv[1];
  357.     if(argc < 3)
  358.         remotename = localname;
  359.     else
  360.         remotename = argv[2];
  361.  
  362.     if(ftp->fp != NULLFILE && ftp->fp != stdout)
  363.         fclose(ftp->fp);
  364.  
  365.     if(ftp->type == IMAGE_TYPE)